/*
 * PlayerTableFile.cpp
 *
 *  Created on: Jul 25, 2013
 *      Author: Dan
 */

#include "PlayerTableFile.h"

namespace sm {

int PlayerTableFile::SUCCESS = 0;
int PlayerTableFile::PLAYERUIDEXISTS = -1;
int PlayerTableFile::ERROROPENINGFILE = -2;
int PlayerTableFile::PLAYERNOTFOUND = -3;
int PlayerTableFile::UNABLETOSWAP = -4;
int PlayerTableFile::BADXML = -5;

PlayerTableFile::PlayerTableFile(const std::string& aFileName) {
	theFileName = aFileName;
	std::ofstream test;
	test.open(aFileName.c_str(), std::ofstream::out | std::ofstream::app);
	if (test.good()) {

	} else {
		Log::error("Could not open player table file.");
	}
	test.close();
}

int PlayerTableFile::addPlayer(const std::string& aName,
		const std::string& aPass, const std::string& aUID) {
	Log::event("Attempt to add Player " + aName);
	int success = SUCCESS;
	std::fstream file;
	file.open(theFileName.c_str(), std::ifstream::in);
	if (file.good()) {
		std::string l;
		while (!file.eof()) {
			getline(file, l);
			if (l.find(aUID) != aUID.npos) {
				Log::error("Player already exists");
				success = PLAYERUIDEXISTS;
			}
		}
		if (success != PLAYERUIDEXISTS) {
			file.close();
			file.open(theFileName.c_str(),
					std::ofstream::out | std::ofstream::app);
			file << std::endl << aName << " " << aPass << " " << aUID;
		}
	} else {
		Log::error("Could not open the players data table file");
		success = ERROROPENINGFILE;
	}
	file.close();
	return success;
}

int PlayerTableFile::rmPlayer(const int& aUID) {
	int success = PLAYERNOTFOUND;
	std::ifstream infile;
	std::ofstream outfile;
	std::string outfilename = theFileName + ".swap";
	infile.open(theFileName.c_str(), std::ifstream::in);
	outfile.open(outfilename.c_str(),
			std::ofstream::out | std::ofstream::trunc);
	if (infile.good() && outfile.good()) {
		std::string l;
		std::stringstream ss;
		ss << aUID;
		while (!infile.eof()) {
			bool first = true;
			getline(infile, l);
			if (l.find(ss.str()) != l.npos) {
				ss << " deleted";
				Log::event(ss.str());
				success = SUCCESS;
			} else if (!l.empty() && !first) {
				outfile << std::endl << l;
			} else if (!l.empty()) {
				outfile << l;
				first = false;
			}
		}
	}
	infile.close();
	outfile.close();
	if (success == SUCCESS) {
		if (remove(theFileName.c_str()) != 0) {
			Log::debug("Could not delete the Player table file");
			success = UNABLETOSWAP;
		} else {
			Log::debug("Deleted the player table file");
			rename(outfilename.c_str(), theFileName.c_str());
			Log::debug("Replaced with swap");
		}
	}
	return success;
}

int PlayerTableFile::changePassword(const int& aUID, const std::string& aPass) {
	int success = PLAYERNOTFOUND;
	std::ifstream infile;
	std::ofstream outfile;
	std::string outfilename = theFileName + ".swap";
	infile.open(theFileName.c_str(), std::ifstream::in);
	outfile.open(outfilename.c_str(),
			std::ofstream::out | std::ofstream::trunc);
	if (infile.good() && outfile.good()) {
		std::string l;
		std::stringstream ss;
		ss << aUID;
		bool first = true;
		while (!infile.eof()) {

			getline(infile, l);
			if(!first){
				outfile<<std::endl;
			}
			else{
				first = false;
			}
			if (l.find(ss.str()) != l.npos) {
				Log::debug("Changed player password");
				outfile << readName(l) << " " << aPass << " "
						<< ss.str();
				success = SUCCESS;
			} else if (!l.empty()) {
				outfile << l;
			}
		}
	}
	infile.close();
	outfile.close();
	if (success == SUCCESS) {
		if (remove(theFileName.c_str()) != 0) {
			Log::debug("Could not delete the Player table file");
			success = UNABLETOSWAP;
		} else {
			Log::debug("Deleted the player table file");
			rename(outfilename.c_str(), theFileName.c_str());
			Log::debug("Replaced with swap");
		}
	}
	return success;
}

std::string PlayerTableFile::listPlayers() {
	Log::debug("Listing players");
	std::string result;
	std::ifstream file;
	file.open(theFileName.c_str(), std::ifstream::in);
	if (file.good()) {
		std::string l;
		while (!file.eof()) {
			getline(file, l);
			if (l != " " && l != "\n")
				result = result + this->readName(l) + " " + this->readUID(l)
						+ "\n";
		}
	}
	return result;
}

std::string PlayerTableFile::readUID(std::string& aLine) {
	unsigned int index = aLine.find_last_of(" ") + 1;
	return aLine.substr(index, aLine.npos - index);
}

std::string PlayerTableFile::readName(std::string& aLine) {
	unsigned int index = aLine.find_first_of(" ");
	return aLine.substr(0, index);
}

std::string PlayerTableFile::readPass(std::string& aLine) {
	unsigned int index1 = aLine.find_first_of(" ") + 1;
	unsigned int index2 = aLine.find_last_of(" ", aLine.npos);
	return aLine.substr(index1, index2 - index1);
}

std::string PlayerTableFile::getPassword(const int& aUID) {
	Log::debug("Looking up player password");
	std::string result;
	std::ifstream file;
	file.open(theFileName.c_str(), std::ifstream::in);
	if (file.good()) {
		std::string l;
		std::stringstream ss;
		ss << aUID;
		while (!file.eof() && result.empty()) {
			getline(file, l);
			if (l.find(ss.str())) {
				Log::debug("Found player password");
				result = readPass(l);
			}
		}
	}
	file.close();
	return result;
}

std::string PlayerTableFile::getName(const int& aUID) {
	Log::debug("Looking up player name");
	std::string result;
	std::ifstream file;
	file.open(theFileName.c_str(), std::ifstream::in);
	if (file.good()) {
		std::string l;
		std::stringstream ss;
		ss << aUID;
		while (!file.eof() && result.empty()) {
			getline(file, l);
			if (l.find(ss.str())) {
				Log::debug("Found player name");
				result = readPass(l);
			}
		}
	}
	file.close();
	return result;
}

Reciept* PlayerTableFile::createreceipt(monkeyXML::XMLTree& anAcctMsg) {
	Reciept* reciept = NULL;
	std::string type = "type";
	monkeyXML::XMLNode* node = anAcctMsg.getNode();
	monkeyXML::XMLTag* tag = static_cast<monkeyXML::XMLTag*>(node);
	monkeyXML::XMLTree* tree;
	bool success = false;
	if (tag->readAttrib(type) == "new") {
		std::string name;
		std::string pass;
		std::string uid;
		for (int i = 0; i < anAcctMsg.childCount(); i++) {
			tree = anAcctMsg.getNextChild();
			if (tree->getTag().find("name") != tree->getTag().npos) {
				name = tree->getNextChild()->getTag();
			} else if (tree->getTag().find("password") != tree->getTag().npos) {
				pass = tree->getNextChild()->getTag();
			} else if (tree->getTag().find("uid") != tree->getTag().npos) {
				uid = tree->getNextChild()->getTag();
			}
		}
		Log::event(std::string("Add Player: ") + name + " " + uid + "\n");
		if (this->addPlayer(name, pass, uid) == SUCCESS)
			success = true;
		reciept = new Reciept(success);
	} else if (tag->readAttrib(type) == "delete") {
		int uid = 0;
		tree = anAcctMsg.getNextChild();
		if (tree->getTag().find("uid") != tree->getTag().npos) {
			std::stringstream convert(tree->getNextChild()->getTag());
			if (!(convert >> uid))
				uid = 0;
			if (this->rmPlayer(uid) == SUCCESS)
				success = true;
		}
		reciept = new Reciept(success);
	} else if (tag->readAttrib(type) == "passwd") {
		std::string pass;
		int uid;
		for (int i = 0; i < anAcctMsg.childCount(); i++) {
			tree = anAcctMsg.getNextChild();
			if (tree->getTag().find("password") != tree->getTag().npos) {
				pass = tree->getNextChild()->getTag();
			} else if (tree->getTag().find("uid") != tree->getTag().npos) {
				std::stringstream convert(tree->getNextChild()->getTag());
				if (!(convert >> uid))
					uid = 0;
			}
		}
		Log::event(std::string("Change password. "));
		if (this->changePassword(uid, pass) == SUCCESS) {
			success = true;
		}
		reciept = new Reciept(success);
	} else if (tag->readAttrib(type) == "list") {
		reciept = new Reciept(this->listtoxml(this->listPlayers()));
	}
	return reciept;
}

std::string PlayerTableFile::listtoxml(const std::string& aList) {
	unsigned i = 0;
	unsigned j = 0;
	std::string xml;
	while (j != aList.npos) {
		if (j != i) {
			if (i == 0) {
				xml += "<player>";
				xml += aList.substr(i, j);
			} else {
				xml += "\n<player>";
				xml += aList.substr(i + 1, j - i - 1);
			}
			xml += "</player>";
		}
		i = j;
		j = aList.find("\n", i + 1);
	}
	return xml;
}

PlayerTableFile::~PlayerTableFile() {
	// TODO Auto-generated destructor stub
}

} /* namespace monkeyXML */
